package com.atung.service.impl;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.atung.config.wx.WxPayClient;
import com.atung.config.wx.WxPayConfig;
import com.atung.dao.BusRoutApplicationDAO;
import com.atung.dao.BusRoutPublishDAO;
import com.atung.dao.BusSchoolBusPaymentDAO;
import com.atung.model.BusRoutApplication;
import com.atung.model.BusRoutPublish;
import com.atung.model.BusRoutPublishDTO;
import com.atung.model.BusSchoolBusPayment;
import com.atung.model.CompanionDTO;
import com.atung.request.RequestApplyRout;
import com.atung.request.RequestRoutApplication;
import com.atung.response.ResponsePublishPathList;
import com.atung.tool.DateTimeTool;
import com.atung.tool.Dictionaries;
import com.atung.tool.SnowflakeIdWorker;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.yuyi.full.Result;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;

@Service
public class RouteJourneyServiceImpl {

	@Autowired
	private StringRedisTemplate stringRedisTemplate;
	@Autowired
	private BusRoutApplicationDAO busRoutApplicationDAO;
	@Autowired
	private BusRoutPublishDAO busRoutPublishDAO;
	@Autowired
	private BusSchoolBusPaymentDAO busSchoolBusPaymentDAO;
	@Autowired
	private PaySuessOrderService paySuessOrderService;
	
	/**
	 * 获取列表
	 * @param routId
	 * @param startDate
	 * @return
	 */
	public List<ResponsePublishPathList> selectBusRoutPublishByRoutId(Long routId,Date startDate){
		 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		 String start=sdf.format(startDate);
		List<ResponsePublishPathList> responsePublishPathLists=new ArrayList<ResponsePublishPathList>();
		
		List<BusRoutPublishDTO> busRoutPublishDTOs=busRoutPublishDAO.selectBusRoutPublishByRoutIdAndStartData(routId, start);

		for(BusRoutPublishDTO busRoutPublishDTO:busRoutPublishDTOs){
			ResponsePublishPathList responsePublishPathList=new ResponsePublishPathList();
			responsePublishPathList.setPublisId(busRoutPublishDTO.getId());
			BeanUtil.copyProperties(busRoutPublishDTO, responsePublishPathList);
			Long expirationData=DateTimeTool.localDateTimeToMillis(busRoutPublishDTO.getExpirationDate())-DateTimeTool.localDateTimeToMillis(LocalDateTime.now());
			if(expirationData<0){
				expirationData=0L;
				if(busRoutPublishDTO.getRoutPublishState()==600){
					busRoutPublishDAO.updateBusRoutPublishByRoutPublishState(busRoutPublishDTO.getId(),601);
				}
				
			}
			responsePublishPathList.setExpirationData(String.valueOf(expirationData));
			if(Objects.nonNull(busRoutPublishDTO.getStartData())){
				Map<String,String>Maps=dataDispose(busRoutPublishDTO.getStartData());
				responsePublishPathList.setWeek(Maps.get("week"));
				responsePublishPathList.setStarDate(Maps.get("starDate"));
				responsePublishPathList.setStarTime((Maps.get("starTime")));
				responsePublishPathLists.add(responsePublishPathList);
			}
		}
		return responsePublishPathLists;
	}
	

	/**
	 * 日历
	 * @param routId
	 * @param startDate
	 * @return
	 */
	public Set<String> selectCalendarDate(Long routId,Date startDate){
		 Set<String>  clalendarDate=new HashSet<>();
		 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		 String start=sdf.format(startDate);
		 Calendar endDateCalendar = Calendar.getInstance();
		 endDateCalendar.add(Calendar.DATE, 30);
		 String endData=sdf.format(endDateCalendar.getTime());
		List<LocalDateTime>calendarLocalDateTime=busRoutPublishDAO.selectRoutPublishByRoutIdProviderAndCalendar(routId, start,endData);
		for(LocalDateTime calebdar:calendarLocalDateTime){	
			if(Objects.nonNull(calebdar)){
				 SimpleDateFormat clalendarFormat = new SimpleDateFormat("yyyy-MM-dd");
				 clalendarDate.add(clalendarFormat.format(new Date(DateTimeTool.localDateTimeToMillis(calebdar))));
			}
		}
		return clalendarDate;
	}
	/**
	 * 获取详情
	 * @param publisId
	 * @return
	 */
	public ResponsePublishPathList selectBusRoutPublishById(Long publisId) {
		// TODO 自动生成的方法存根
		ResponsePublishPathList responsePublishPathList=new ResponsePublishPathList();
		BusRoutPublishDTO busRoutPublishDTO=busRoutPublishDAO.selectBusRoutPublishMessageById(publisId);
		if(Objects.isNull(busRoutPublishDTO)){
			return responsePublishPathList;
		}
		responsePublishPathList.setPublisId(busRoutPublishDTO.getId());
		BeanUtil.copyProperties(busRoutPublishDTO, responsePublishPathList);
		Long expirationData=DateTimeTool.localDateTimeToMillis(busRoutPublishDTO.getExpirationDate())-DateTimeTool.localDateTimeToMillis(LocalDateTime.now());
		responsePublishPathList.setExpirationData(expirationData.toString());
		if(Objects.nonNull(busRoutPublishDTO.getStartData())){
			Map<String,String>Maps=dataDispose(busRoutPublishDTO.getStartData());
			responsePublishPathList.setWeek(Maps.get("week"));
			responsePublishPathList.setStarDate(Maps.get("starDate"));
			responsePublishPathList.setStarTime((Maps.get("starTime")));
		}
		return responsePublishPathList;
	}
	
	public Result insertBusRoutApplication(RequestRoutApplication request){
		BusRoutApplication busRoutApplication=busRoutApplicationDAO.selectRoutApplicationByOpenidAndDepartlIdAndDestinationId(request.getOpenId(),
				request.getDepartlId(), request.getDestinationId());
		if(Objects.nonNull(busRoutApplication)){
			return Result.error(202);
		}
		BusRoutApplication busRoutApplication2=new BusRoutApplication();
		BeanUtil.copyProperties(request, busRoutApplication2);
		busRoutApplication2.setCreationTime(LocalDateTime.now());
		busRoutApplication2.setModificationTime(LocalDateTime.now());
		busRoutApplication2.setId(SnowflakeIdWorker.nextId());
		busRoutApplication2.setApplicationOpenId(request.getOpenId());
		Boolean save=busRoutApplicationDAO.saveRoutApplication(busRoutApplication2);
		if(!save){
			return Result.error(203);
		}
		Integer countNumber=busRoutApplicationDAO.countRoutApplicationByDepartlIdAndDestinationId(request.getDepartlId(), request.getDestinationId());
		return Result.success(countNumber);
	}
	
	public Map<String,String>dataDispose(LocalDateTime stateDate){
		String[] week=new String[]{"周日","周一","周二","周三","周四","周五","周六"};
		Map<String,String> maps=new HashMap<String, String>();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date(DateTimeTool.localDateTimeToMillis(stateDate)));
		int weeks =calendar.get(Calendar.DAY_OF_WEEK);
		maps.put("week", week[weeks-1]); 
		maps.put("starDate", String.format(" %02d",(calendar.get(Calendar.MONTH) + 1))+"-"+String.format(" %02d",calendar.get(Calendar.DATE)));
		maps.put("starTime",String.format(" %02d",calendar.get(Calendar.HOUR_OF_DAY))+":"+String.format(" %02d",calendar.get(Calendar.MINUTE)));
		return maps;
	}

	/**
	 * 报名
	 * @param request
	 * @throws Exception 
	 */
	@Transactional
	public Map<String, String> applyRoutPublish(@Valid RequestApplyRout request) throws Exception {
		// TODO 自动生成的方法存根

		BigDecimal  totaPrices=request.getTotalPrices();
		//获取应支付总价格
		BusRoutPublish busRoutPublish=busRoutPublishDAO.selectBusRoutPublishById(request.getPublishRoutId());
	
		if(Objects.isNull(busRoutPublish)){
			throw new Exception("暂无路线");
		}else if(!Objects.equals(busRoutPublish.getRoutPublishState(), 600)){
			throw new Exception("暂无路线");
		}
		if(request.getCompanionlist().size()>busRoutPublish.getAllocationNumber()){
			throw new Exception("您的人员报名过多，无法分配一辆车");
		}
		if(busRoutPublish.getCarCurrentNumber()>busRoutPublish.getCarMaxRideNumber()){
			throw new Exception("报名人数过多，请选择别的时间。或者联系校区负责人");
		}
		BigDecimal orderPayable=new BigDecimal(0.00);
		for(CompanionDTO companion:request.getCompanionlist()){
			orderPayable=orderPayable.add(busRoutPublish.getCarRidPrice());
		}
		if(orderPayable.compareTo(totaPrices) != 0){
			throw new Exception("付款金额异常");
		}
		Long paymentId=SnowflakeIdWorker.nextId();
		String platformOrderNumber =UUID.randomUUID().toString();
		stringRedisTemplate.opsForValue().set(Dictionaries.schoolBusOrderReidKey+platformOrderNumber,JSONObject.toJSONString(request.getCompanionlist()), 50,TimeUnit.MINUTES);
		BusSchoolBusPayment busSchoolBusPayment=new BusSchoolBusPayment();
		busSchoolBusPayment.setId(paymentId);
		busSchoolBusPayment.setRoutPublishId(busRoutPublish.getId());
		busSchoolBusPayment.setPlatformOrderNumber(platformOrderNumber);
		busSchoolBusPayment.setOrderPayableMoney(orderPayable);
		busSchoolBusPayment.setCreationTime(LocalDateTime.now());
		busSchoolBusPayment.setModificationTime(LocalDateTime.now());
		busSchoolBusPayment.setOrderStatus(201);
		busSchoolBusPayment.setOpenId(request.getOpenId());
		busSchoolBusPayment.setOrderCreateTime(LocalDateTime.now());
		if(!busSchoolBusPaymentDAO.saveBusSchoolBusPayment(busSchoolBusPayment)){
			throw new Exception("报名失败");
		};
		Map<String,String> payParam=wxPayService(busSchoolBusPayment.getOpenId(),paymentId,orderPayable);
		if(Objects.isNull(payParam)){
			throw new Exception("签名验证失败");
		}
		return payParam;

	}
	
	
	//微信支付
	public Map<String,String> wxPayService(String openId,Long paymentId,BigDecimal orderPrice){
        try{
            String body = "惠同便行";
            //支付金额，单位：分，这边需要转成字符串类型，否则后面的签名会失败
            BigDecimal money = orderPrice.multiply(new BigDecimal("100.00"));
            String totalFee = money.toString().substring(0,money.toString().indexOf("."));
            Map<String, String> resp = WxPayClient.getOrder(openId,paymentId.toString(),body,totalFee);
            String returnCode = resp.get("return_code");
            String resultCode = resp.get("result_code");
            String errCodeDes = resp.get("err_code_des");
            if (Objects.equals(resultCode,"SUCCESS") || returnCode.equals(resultCode)) {
                Map<String,String> param = new HashMap<>();
                String timeStamp = String.valueOf(new Date().getTime());
                timeStamp = timeStamp.substring(0,timeStamp.length()-3);
                String noncestr = resp.get("nonce_str");
                // 业务结果
                String prepay_id = (String) resp.get("prepay_id");//预支付交易会话标识
                param.put("appId",WxPayConfig.jsappid);
                param.put("nonceStr", noncestr);
                param.put("package", "prepay_id=" + prepay_id);
                param.put("timeStamp", timeStamp);
                param.put("signType", "HMAC-SHA256");
                String sign = WXPayUtil.generateSignature(param,WxPayConfig.key, WXPayConstants.SignType.HMACSHA256);
                param.put("paySign",sign);
                return param;
            }
          
        }catch(Exception e){
            e.printStackTrace();
        }
        return null;
    }
}
